home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-06-01 | 29.6 KB | 1,090 lines | [TEXT/MPS ] |
- // Copyright ©1994 Apple Computer, Inc.
- // Author: John Powers
- // Date: 13-Mar-94
-
- // UAppMo.cp
- // The derived application class for MoGuide.
-
- #ifndef __UAPPMO__
- #include "UAppMo.h"
- #endif
-
- #include <Dialogs.h>
-
- extern Boolean gAGuideAvailable;
-
- // Segment
-
- #pragma segment Main
-
- // ------------------------------------------------------------------------
- // TAppMo::HandleAECustom
- // Handles the custom events.
- // The refCon contains our application object.
- // Should be in a locked, unpurgeable segment.
- //
- // Unfortunately, the DTS sample TApplication does not process
- // high level events. We fix that by overriding the EventLoop
- // and adding high-level event processing.
- //
- pascal OSErr
- TAppMo::HandleAECustom(AppleEvent& theAppleEvent,
- AppleEvent& /*theReply*/, long refCon)
- {
- OSType eventId;
- Size actualSize;
- DescType returnedType;
- OSErr err=noErr;
- // Useless without our application object.
- TAppMo* ourApp=(TAppMo*)refCon;
- if(!ourApp)
- return kErrNoAppObject;
- // Get a potential document collaboarator.
- TDocArt* docArt = ourApp->GetDocArt();
- // Get event id.
- err = AEGetAttributePtr(&theAppleEvent, keyEventIDAttr,
- typeType, &returnedType,
- (Ptr) &eventId, sizeof(eventId),
- &actualSize);
- switch (eventId)
- {
- case kAEIdCloseDocArt:
- ourApp->CloseDoc(ourApp->fDocArt);
- break;
- case kAEIdShowDocArt:
- ourApp->ShowArt();
- ourApp->DoAdvance();
- break;
- case kAEIdCloseDocFB:
- ourApp->CloseDoc(ourApp->fDocFB);
- break;
- case kAEIdShowDocFB:
- ourApp->ShowFeedback();
- break;
- case kAEIdReset:
- if(docArt)
- docArt->SetWantReset();
- break;
- case kAEIdShuffle:
- if(docArt)
- docArt->SetWantShuffle();
- break;
- case kAEIdQuitApp:
- ourApp->ExitLoop();
- break;
- case kAEIdWaitCollision:
- // The context check will set the event.
- // If the event is constant, we could set it
- // right here and skip the context check.
- // Otherwise, we need the context check to
- // send us the event that the author desires.
- if(docArt)
- docArt->SetWantCollision(true);
- break;
- case kAEIdIgnoreCollision:
- // Ignore any collision,
- // turn off flag and clear event.
- if(docArt)
- {
- docArt->SetWantCollision(false);
- docArt->SetCollisionEvent(0);
- }
- break;
- case kAEIdAdvance:
- // Advance on the next open-window event.
- ourApp->SetOkayAdvance(true);
- break;
- default:
- err = errAEEventNotHandled;
- break;
- }
- if(ourApp->fFBEvent)
- ourApp->fFBEvent->SetFlash(eventId);
- return err;
-
- }
-
- // --------------------------------------------------------------------
- // TAppMo::ReplyToCoach
- //
- // This is a callback invoked by the Coach Apple event handler.
- // This member function and the refCon
- // was provided by us in the Init call.
- //
- // Handles replies for Coach queries sent to OurApp.
- // Called with the item name and refCon.
- // Return the item Rect and a result code.
- //
- // The name is a zero-terminated string (C-string).
- // equalstring requires an A5 world.
- //
- // Caveats:
- //
- // Our app resource map is not available.
- // If you need a resource such as a string,
- // read it in advance and save it in memory.
- //
- // A static function in main segment.
- pascal OSErr
- TAppMo::ReplyToCoach(Rect* pItemRect, Ptr pName, long refCon)
- {
- OSErr result=kAGErrItemNotFound;
- // We probably need an A5 world.
- long restoreGlobals = SetA5(*(long*)LMGetCurrentA5());
- // Our application object is in the refcon.
- TAppMo* ourApp=(TAppMo*) refCon;
- if(ourApp)
- {
- // Ask our document window for the rect of the named item.
- if(ourApp->fDocArt->GetLocation(pName, pItemRect))
- {
- GrafPtr savePort;
- // Return the rectangle in global coordinates
- GetPort(&savePort);
- // Get the GrafPort.
- SetPort((GrafPtr) ourApp->fDocArt->GetDocWindow());
- // Top-left
- LocalToGlobal((Point*)&(pItemRect->top));
- // Bottom-right
- LocalToGlobal((Point*)&(pItemRect->bottom));
- SetPort(savePort);
- result = noErr;
- }
- // Feedback - auditory and visual
- if(ourApp->fFBCoach)
- ourApp->fFBCoach->SetFlash(pName);
- } // if(ourApp…
- SetA5(restoreGlobals);
- return(result);
- }
-
- // ------------------------------------------------------------------------
- // TContext::ReplyToContext
- // Handles replies for context checks sent to OurApp.
- // Called with the data in the context check database object
- // and the event you sent in the Init.
- // Return the result (true or false).
- // A callback.
- // A static function in main segment.
- pascal OSErr
- TContext::ReplyToContext(Ptr pInput, Size inputDataSize,
- Ptr *ppOutput, Size *pOutputDataSize,
- AGAppInfoHdl hAppInfo)
- {
- OSErr err=noErr;
- long inputValue=0;
- short result=false;
- // We probably need an A5 world.
- long restoreGlobals = SetA5(*(long*)LMGetCurrentA5());
- // The input value can be used by either event id.
- if(pInput && inputDataSize>0)
- {
- inputValue = *((long*)pInput);
- }
- // Our application object was passed by us in the refCon.
- // It is returned to us in the refcon of hAppInfo.
- TAppMo* ourApp = (TAppMo*) (**hAppInfo).refCon;
- // Which event id?
- switch ((**hAppInfo).eventId)
- {
- // kAEIdContextCollision
- // Set the collision event to the inputValue.
- // When a collision occurs, the event will
- // be sent to Apple Guide. In other words,
- // Apple Guide is saying "Let me know when
- // a collision occurs by sending me this event."
- // A zero input value cancels the event.
- // Always returns a false result.
- case kAEIdContextCollision:
- if(ourApp->fDocArt)
- if(ourApp->fDocArt->WantCollision())
- ourApp->fDocArt->SetCollisionEvent(inputValue);
- result = false;
- break;
- // kAEIdContextBeep
- // Return the value (true or false) saved in fBeepReturn.
- case kAEIdContextBeep:
- result = ourApp->fBeepReturn;
- break;
- // kAEIdContextWindow
- // Return true if a document window is open and showing.
- case kAEIdContextWindow:
- result = (ourApp->fDocArt)?ourApp->fDocArt->IsWindowVisible():false;
- break;
- default:
- // An unknown event will be ignored.
- break;
- }
- // Create storage for our result.
- *ppOutput = NewPtr(sizeof(short));
- if(*ppOutput)
- {
- // Set the result and its size.
- **ppOutput = result;
- *pOutputDataSize = sizeof(short);
- }
- // Feedback - auditory and visual
- if(ourApp->fFBContext)
- ourApp->fFBContext->SetFlash((**hAppInfo).eventId);
-
- SetA5(restoreGlobals);
- return err;
- }
-
- // Segment
-
- #pragma segment MoG1
-
- // =========================================================================
- // TAppMo
- // ------------------------------------------------------------------------
- TAppMo::TAppMo()
- {
- };
-
- // ------------------------------------------------------------------------
- // TAppMo::AddGuideFiles
- // Add the guide files to the mMoGuide menu.
- //
- // If there are any files, a dashed line is added first,
- // followed by the menu name for each file. We save
- // the FSSpec's for easy retrieval when the user chooses
- // the menu item. If any guide files already exist on
- // the menu, they are deleted first and a fresh list
- // is prepared.
- //
- void
- TAppMo::AddGuideFiles()
- {
- short newFileCount;
- Str63 menuName;
- FSSpec fileSpec;
- MenuHandle hmMoGuide = GetMHandle(mMoGuide);
- if(hmMoGuide)
- {
- // If we already have a file list, delete it.
- if(this->fhFileList)
- {
- // We do, dispose of it and its menu items.
- DisposeHandle(this->fhFileList);
- while(this->fFileCount--)
- {
- // Delete the item after the dash line.
- DelMenuItem(hmMoGuide, iLastMenuItem+2);
- }
- // Delete dashed line.
- DelMenuItem(hmMoGuide, iLastMenuItem+1);
- }
- // Set the search directory for guide files.
- short vRefNum = (-*(short*)LMGetSFSaveDisk());
- long dirID = (*(long*)LMGetCurDirStore());
- Boolean wantMixin = false;
- newFileCount = AGFileGetDBCount(vRefNum, dirID,
- kAGFileDBTypeAny, wantMixin);
-
- if(newFileCount>0)
- {
- // Create a new list of file FSSpecs.
- this->fhFileList = NewHandle(newFileCount*sizeof(FSSpec));
- if(this->fhFileList)
- {
- // Add dashed line.
- AppendMenu(hmMoGuide, (const unsigned char*)"\p-");
- // Get each file, add to menu and to list.
- this->fFileCount = newFileCount;
- for(short i=1; i<=newFileCount; i++)
- {
- // Use same vRefNum, dirID, and wantMixin
- // that was set for the count.
- if(AGFileGetIndDB(vRefNum, dirID,
- kAGFileDBTypeAny, wantMixin,
- i, &fileSpec)==noErr)
- {
- if(AGFileGetDBMenuName(&fileSpec, menuName)==noErr)
- {
- // We have a guide file,
- // get it's menu name and add to menu.
- AppendMenu(hmMoGuide, menuName);
- ((FSSpec*)(*this->fhFileList))[i-1] = fileSpec;
- }
- }
- } // for(short…
- } // if(hFileMenu…
- } // if(newFileCount…
- } // if(hmMoGuide…
- }
-
- // --------------------------------------------------------------------------
- // TAppMo::AdjustMenus
- //
- void
- TAppMo::AdjustMenus() // override
- {
- // Inherit first.
- TApp::AdjustMenus();
- // Our menus.
- MenuHandle hmMoGuide=GetMHandle(mMoGuide);
- MenuHandle hmWindow=GetMHandle(mWindow);
- // Always enabled
- EnableItem(hmMoGuide, iFiles);
- // Set default case.
- DisableItem(hmMoGuide, iStartGuide);
- DisableItem(hmMoGuide, iQuitGuide);
- DisableItem(hmMoGuide, iOpenDefault);
- DisableItem(hmMoGuide, iClose);
- // If Apple Guide is installed, then we can do lots of things.
- if(gAGuideAvailable)
- {
- AGStatus status = AGGetStatus();
- // Permit starting it if it's not already started.
- if(status==kAGIsNotRunning)
- EnableItem(hmMoGuide, iStartGuide);
- // If Apple Guide is sleeping, then we can make it quit.
- else if(status==kAGIsSleeping)
- EnableItem(hmMoGuide, iQuitGuide);
- // If we have default help available, then we can open it.
- if(AGGetAvailableDBTypes() & kAGDBTypeBitHelp)
- EnableItem(hmMoGuide, iOpenDefault);
- // If we have a non-nil this->fGuideRefNum,
- // then a database is open. Permit closing.
- // this->fGuideRefNum is tracked in TApp::AdjustMenus.
- if(this->fGuideRefNum)
- EnableItem(hmMoGuide, iClose);
- // Enable any databases that we may have added.
- for(short i=0; i<this->fFileCount; i++)
- EnableItem(hmMoGuide, iLastMenuItem+i+2);
- }
- // Always available.
- // Art-related items.
- EnableItem(hmWindow, iWinArt);
- // Can reset objects if a window is visible.
- if(this->fDocArt)
- {
- EnableItem(hmWindow, iResetArt);
- EnableItem(hmWindow, iShuffleArt);
- }
- else
- {
- DisableItem(hmWindow, iResetArt);
- DisableItem(hmWindow, iShuffleArt);
- }
- // Always available.
- EnableItem(hmWindow, iFeedback);
- EnableItem(hmWindow, iContextTrue);
- CheckItem(hmWindow, iContextTrue, this->fBeepReturn);
- EnableItem(hmWindow, iContextBeep);
- if(this->fFBContext)
- CheckItem(hmWindow, iContextBeep, this->fFBContext->GetBeep());
-
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::CheckFrontWindow
- // Check to see if Apple Guide has a window showing.
- // Update the miscellaneous feedback with the result.
- // We look for the front window of the current database
- // which is not necessarily our own. If we wanted just
- // our own database, we would pass this->fGuideRefNum
- // instead of kAGFrontDatabase.
- //
- void
- TAppMo::CheckFrontWindow()
- {
- Str255 string;
- short index=kStrNone;
- if(gAGuideAvailable)
- {
- // If Apple Guide is available, then the choices
- // are nothing (Apple Guide is not running),
- // sleeping, access window, or presentation window.
- if(AGGetStatus()!=kAGIsNotRunning)
- {
- AGWindowKind kind = AGGetFrontWindowKind(kAGFrontDatabase);
- // Clarity, not conciseness.
- if(kind==kAGNoWindow)
- index = kStrNoneSleeping;
- else if(kind==kAGAccessWindow)
- index = kStrAccess;
- else if(kind==kAGPresentationWindow)
- index = kStrPresentation;
- }
- }
- // Update FBMisc if there is a change.
- // It flashes every time we update it.
- // We force an update every kMaxStatusUpdateCnt cycles.
- this->fLastStatusCnt--;
- if(this->fLastStatusCnt==0 || index!=this->fLastMiscIndex)
- {
- GetIndString(string, kFrontWindowStrId, index);
- // If we are in the idle loop, we must check this->fFBMisc
- // validity in case it hasn't been created yet.
- if(this->fFBMisc)
- {
- this->fFBMisc->SetFlash(string);
- this->fLastMiscIndex = index;
- }
- this->fLastStatusCnt = kMaxStatusUpdateCnt;
- }
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::DoAdvance
- // If an advance is wanted, do it.
- // This is a one-shot event.
- // We send a go-back event because we assume that Apple Guide
- // is showing an oops panel.
- void
- TAppMo::DoAdvance()
- {
- if(gAGuideAvailable && this->fOkayAdvance)
- {
- AlertIfError(AGGeneral(this->fGuideRefNum, kAGEventReturnBack));
- }
- this->fOkayAdvance = false;
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::DoGoAway
- //
- // This is the close side of TAppMo::ShowArt, ShowClipboard, ShowFeedback.
- //
- void
- TAppMo::DoGoAway()
- {
- // Clear our local document record if
- // it's object is going away.
- if(this->fCurDoc==this->fDocFB)
- {
- this->fDocFB = nil;
- this->fFBContext->SetDoc(nil);
- this->fFBCoach->SetDoc(nil);
- this->fFBEvent->SetDoc(nil);
- this->fFBMisc->SetDoc(nil);
- }
- else if(this->fCurDoc==this->fDocArt)
- this->fDocArt = nil;
- // Inherit go-away action from TApp and TApplication
- TApp::DoGoAway();
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::DoIdle
- // Do our idle and deferred events.
- //
- void
- TAppMo::DoIdle() // override
- {
- // Inherit to do TApp Idle.
- TApp::DoIdle();
- // Document actions.
- if(this->fDocArt)
- this->fDocArt->DoIdle();
- // Feedback about context-checking.
- if(this->fFBContext)
- this->fFBContext->DoIdle();
- // Feedback about Coach objects.
- if(this->fFBCoach)
- this->fFBCoach->DoIdle();
- // Feedback about Apple events.
- if(this->fFBEvent)
- this->fFBEvent->DoIdle();
- // Check for Apple Guide front window.
- this->CheckFrontWindow();
- // Miscellaneous feedback.
- if(this->fFBMisc)
- this->fFBMisc->DoIdle();
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::DoMenuCommand
- // This is called when an item is chosen from the menu bar (after calling
- // MenuSelect or MenuKey). It does the right thing for each command.
- //
- // TAppMo::AdjustMenus enables the menu items
- // depending on whether or not guide is available.
- // Consequently, we don't have to check here to see
- // if guide is available because, if it isn't, the item
- // won't be choosen.
- //
- void
- TAppMo::DoMenuCommand(short menuID, short menuItem) // override
- {
- FSSpec fileSpec;
- OSErr err=noErr;
- switch (menuID)
- {
- case mMoGuide:
- switch(menuItem)
- {
- case iStartGuide:
- AlertIfError(AGStart());
- break;
- case iQuitGuide:
- AlertIfError(AGQuit());
- break;
- case iOpenDefault:
- AlertIfError(this->OpenGuideDatabase((FSSpec*)kAGDefault));
- break;
- case iClose:
- err = AGClose(&this->fGuideRefNum);
- if(err==kAGErrDatabaseNotOpen)
- this->fGuideRefNum = nil;
- break;
- case iFiles:
- this->AddGuideFiles();
- break;
- default:
- // Must be one of the guide file items that we added.
- // Get its FSSpec from the list and open it.
- if(this->fhFileList)
- {
- fileSpec = ((FSSpec*)(*this->fhFileList))[menuItem-iLastMenuItem-2];
- AlertIfError(this->OpenGuideDatabase(&fileSpec));
- }
- break;
- } // switch
- break;
- case mWindow:
- switch(menuItem)
- {
- case iWinArt:
- err = this->SendEventToSelf(kAEIdShowDocArt);
- break;
- case iFeedback:
- err = this->SendEventToSelf(kAEIdShowDocFB);
- break;
- case iContextTrue:
- this->fBeepReturn = !this->fBeepReturn;
- break;
- case iContextBeep:
- if(this->fFBContext)
- this->fFBContext->SetBeep(!this->fFBContext->GetBeep());
- break;
- case iResetArt:
- err = this->SendEventToSelf(kAEIdReset);
- break;
- case iShuffleArt:
- err = this->SendEventToSelf(kAEIdShuffle);
- break;
- default:
- break;
- } // switch
- break;
- default:
- break;
- } // switch
- // Inherit for the Apple, File, and Edit menus.
- TApp::DoMenuCommand(menuID, menuItem);
- AlertIfError(err);
- } // DoMenuCommand
-
- // ---------------------------------------------------------------------
- // TAppMo::Init
- // Do the things that our derived application class requires.
- // Basic initialization, before we start.
- // We store our application object in the core event handler
- // refCon so that the handler can use it. Avoids making it a global.
- // Return noErr if successful.
- OSErr
- TAppMo::Init()
- {
- // Inherit
- OSErr err = TApp::Init();
- if(err==noErr)
- {
- // Override the menubar ID.
- this->fMenuBarID = rMenuBarMo;
- // Clear our collaborators because we'll not want to use
- // them until after we get the core startup event.
- // Clear handler refNums.
- this->fCoachRefNum = nil;
- this->fContext = nil;
- this->fFBContext = nil;
- this->fFBCoach = nil;
- this->fFBEvent = nil;
- this->fFBMisc = nil;
- this->fDocArt = nil;
- this->fDocFB = nil;
- // Also clear our variables or we may get a bus error
- // at the first DoIdle (before we get the start event.)
- this->fhFileList = nil;
- this->fFileCount = 0;
- this->fBeepReturn = false;
- this->fOkayAdvance = false;
- this->fLastMiscIndex = 0;
- // Remove the core event handler installed in TApp.
- (void) AERemoveEventHandler(kCoreEventClass,
- typeWildCard,
- kHandlerNotRequired,
- kIsNotSysHandler);
- // Replace with a core event handler which
- // uses the same handler, but passes TAppMo
- // in the refCon instead of TApp. This
- // insures that TAppMo::Start is invoked.
- err = AEInstallEventHandler(kCoreEventClass,
- typeWildCard,
- #ifdef __powerc
- NewAEEventHandlerProc(TApp::HandleAECore),
- #else
- TApp::HandleAECore,
- #endif
- (long)this,
- kIsNotSysHandler);
- // Install our custom event handler.
- // We put the TAppMo object in the refCon.
- err = AEInstallEventHandler(kAEClassCustom,
- typeWildCard,
- #ifdef __powerc
- NewAEEventHandlerProc(TAppMo::HandleAECustom),
- #else
- TAppMo::HandleAECustom,
- #endif
- (long)this,
- kIsNotSysHandler);
- // Initialize our status update cycle counter.
- this->fLastStatusCnt = kMaxStatusUpdateCnt;
- // Starting is done in TApp::HandleAECore.
- // We wait until that happens before proceeding.
- }
- return err;
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::Quit
- // We're quitting, so delete everything.
- // All of this probably goes away in the application heap anyway,
- // we're just being compulsively tidy.
- //
- void
- TAppMo::Quit()
- {
- if(gAGuideAvailable)
- {
- // Remove Coach and context handlers.
- AlertIfError(AGRemoveCoachHandler(&this->fCoachRefNum));
- }
- // Delete our context object.
- if(this->fContext)
- {
- AlertIfError(this->fContext->Remove());
- delete this->fContext;
- }
- // Delete our flasher objects.
- if(this->fFBContext)
- delete this->fFBContext;
- if(this->fFBCoach)
- delete this->fFBCoach;
- if(this->fFBEvent)
- delete this->fFBEvent;
- if(this->fFBMisc)
- delete this->fFBMisc;
- // Remove list of guide files.
- if(this->fhFileList)
- DisposeHandle(this->fhFileList);
- // Remove custom event handler.
- (void) AERemoveEventHandler(kAEClassCustom,
- typeWildCard,
- kHandlerNotRequired,
- kIsNotSysHandler);
- // Inherit.
- TApp::Quit();
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::ShowArt
- // Opens the art window.
- // The document window is closed by the go-away box (TAppMo::DoGoAway).
- //
- // The art is specified in a resource.
- // The art resource id matches the id of its window.
- // To add another window, specify a new resource id,
- // define the new art resource, and instantiate a new TDocArt.
- //
- void
- TAppMo::ShowArt()
- {
- if(this->fDocArt==nil)
- {
- // Art window is not present.
- // Create a document and window for the art.
- this->fDocArt = new TDocArt(kArt1WindResID);
- if(this->fDocArt)
- {
- // Add new document to document list.
- this->fDocList->AddDoc((TDocument*) this->fDocArt);
- // Update current document and window pointer.
- this->fCurDoc = this->fDocArt;
- this->fWhichWindow = this->fCurDoc->GetDocWindow();
- SetPort(this->fWhichWindow);
- // Initialize art document window.
- AlertIfError(this->fDocArt->Init(kArt1WindResID));
- // Set the application object as a collaborator.
- this->fDocArt->SetApp(this);
- }
- }
- // Better show it, or at least bring it to the front.
- this->fDocArt->Show();
- // Invalidate window so that it will be updated and drawn.
- this->fDocArt->Invalidate();
- }
-
- // ------------------------------------------------------------------------
- // TAppMo::ShowFeedback
- // Opens the feedback window.
- // The document window is closed by the go-away box (TAppMo::DoGoAway).
- //
- void
- TAppMo::ShowFeedback()
- {
- if(this->fDocFB==nil)
- {
- // Feedback window is not present.
- // Create a document and window for the feedback.
- this->fDocFB = new TDocFB(kFeedbackWinResID);
- if(this->fDocFB)
- {
- // Add new document to document list.
- this->fDocList->AddDoc((TDocument*) this->fDocFB);
- // Update current document and window pointer.
- this->fCurDoc = this->fDocFB;
- this->fWhichWindow = this->fCurDoc->GetDocWindow();
- SetPort(this->fWhichWindow);
- // Initialize feedback document window.
- AlertIfError(this->fDocFB->Init());
- // Set the application object as a collaborator.
- this->fDocFB->SetApp(this);
- // Set document window collaborator for feedback.
- this->fFBContext->SetDoc(this->fDocFB);
- this->fFBCoach->SetDoc(this->fDocFB);
- this->fFBEvent->SetDoc(this->fDocFB);
- this->fFBMisc->SetDoc(this->fDocFB);
- }
- }
- // Better show it, or at least bring it to the front.
- this->fDocFB->Show();
- // Invalidate window so that it will be updated and drawn.
- this->fDocFB->Invalidate();
- }
-
- // ---------------------------------------------------------------------
- // TAppMo::Start
- // Startup the application.
- // The Init is done in main. The Start comes with the oapp or odoc event.
- // Return noErr if successful.
- OSErr
- TAppMo::Start()
- {
- // Inherit.
- OSErr err = TApp::Start();
- {
- // Reply to Coach mark queries.
- // Pass along the TApp object.
- // Setup our callbacks for context-check queries.
- // Pass along the TApp object in the refCon.
- if(gAGuideAvailable)
- {
- err = AGInstallCoachHandler(NewCoachReplyProc(TAppMo::ReplyToCoach),
- (long)this, &this->fCoachRefNum);
- if(err!=noErr)
- return err;
- this->fContext = new TContext;
- if(this->fContext)
- err = this->fContext->Install((long)this);
- else
- err = kErrNoContextObject;
- if(err!=noErr)
- return err;
- }
- // List of guide files.
- this->fhFileList = nil;
- this->fFileCount = 0;
- // Don't want a panel advance yet.
- this->fOkayAdvance = false;
- // Return a true or false to the beep context check query?
- this->fBeepReturn = false;
- // Feedback (the Flasher).
- this->fFBContext = new TFeedback;
- if(this->fFBContext)
- this->fFBContext->Init(this, dataCC);
- this->fFBCoach = new TFeedback;
- if(this->fFBCoach)
- this->fFBCoach->Init(this, dataCH);
- this->fFBEvent = new TFeedback;
- if(this->fFBEvent)
- this->fFBEvent->Init(this, dataEV);
- this->fFBMisc = new TFeedback;
- if(this->fFBMisc)
- {
- this->fFBMisc->Init(this, dataTP);
- // Set an infinite interval for FBMisc.
- this->fFBMisc->SetInterval(0);
- }
- // Show the feedback window/document.
- err = this->SendEventToSelf(kAEIdShowDocFB);
- }
- return err;
- }
-
- // =========================================================================
- // TContext
- // ------------------------------------------------------------------------
- TContext::TContext()
- {
- this->fHandlerCnt = 0;
- }
-
- // ------------------------------------------------------------------------
- TContext::~TContext()
- {
- // If we still have handlers installed, remove them.
- if(this->fHandlerCnt>0)
- (void) this->Remove();
- }
-
- // ------------------------------------------------------------------------
- // TContext::Install
- // Install context-check handlers.
- // The appObj is the application object
- // used in the reply to access the application.
- // If any error occurs, return it.
- //
- OSErr
- TContext::Install(long appObj)
- {
- OSErr result=noErr;
- OSErr eachResult;
- // Define and install context-check handlers.
- // If we still have handlers installed, remove them.
- if(this->fHandlerCnt>0)
- result = this->Remove();
- this->fHandlerCnt = kContextHandlerCnt;
- this->fContext[0].eventID = kAEIdContextCollision;
- this->fContext[1].eventID = kAEIdContextBeep;
- this->fContext[2].eventID = kAEIdContextWindow;
- for(short i=0; i<this->fHandlerCnt; i++)
- {
- // Install handler.
- // If an error, the refNum will be set to nil by Apple Guide.
- eachResult = AGInstallContextHandler(
- NewContextReplyProc(TContext::ReplyToContext),
- this->fContext[i].eventID,
- appObj,
- &this->fContext[i].refNum);
- // Track only errors in result.
- result = (eachResult!=noErr)?eachResult:result;
- }
- return result;
- }
-
- // ------------------------------------------------------------------------
- // TContext::Remove
- // Remove context-check handlers.
- // If any error occurs, return it.
- //
- OSErr
- TContext::Remove()
- {
- OSErr result=noErr;
- OSErr eachResult;
- for(short i=0; i<this->fHandlerCnt; i++)
- {
- eachResult = AGRemoveContextHandler(&this->fContext[i].refNum);
- // Track only errors in result.
- result = (eachResult!=noErr)?eachResult:result;
- }
- this->fHandlerCnt = 0;
- return result;
- }
-
- // =========================================================================
- // TTypeStr
- // ------------------------------------------------------------------------
- TTypeStr::TTypeStr(OSType theType)
- {
- TypeToChar toConvert;
- toConvert.type = theType;
- // Convert stored OSType to pstring.
- // Replace zeros with spaces.
- this->fString[0] = 4;
- for(short i=0; i<4; i++)
- this->fString[i+1] = (toConvert.ch[i])?toConvert.ch[i]:' ';
- }
-
- // ------------------------------------------------------------------------
- // TTypeStr::String
- StringPtr
- TTypeStr::String()
- {
- return &this->fString[0];
- }
-
- // =========================================================================
- // TFeedback
- // ------------------------------------------------------------------------
- TFeedback::TFeedback()
- {
- this->fShowTime = 0;
- this->fInterval = kIntervalShow;
- this->fCurrent = 0;
- this->fPrevious = 0;
- this->fShow = false;
- this->fBeep = false;
- this->fOurApp = nil;
- this->fDocFB = nil;
- }
-
- // ------------------------------------------------------------------------
- TFeedback::~TFeedback()
- {
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::DoIdle
- // Do any action required during the idle processing.
- //
- void
- TFeedback::DoIdle()
- {
- this->Show();
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::Draw
- void
- TFeedback::Draw(OSType toDraw, short mode)
- {
- TTypeStr flashChar = toDraw;
- // Draw it in the feedback window (if present).
- if(this->fDocFB)
- this->fDocFB->DrawData(flashChar.String(), mode, this->fWhichData);
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::GetBeep
- // Return the want-beep flag.
- Boolean
- TFeedback::GetBeep()
- {
- return this->fBeep;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::Init
- // Set the application collaborator (and any others you might want to add.)
- void
- TFeedback::Init(TAppMo* theApp, short whichData)
- {
- // The collaborator
- this->fOurApp = theApp;
- // The data
- this->fWhichData = whichData;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::SetBeep
- // Set the want-beep flag.
- void
- TFeedback::SetBeep(Boolean wantBeep)
- {
- this->fBeep = wantBeep;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::SetFlash
- void
- TFeedback::SetFlash(OSType theFlash)
- {
- this->fCurrent = theFlash;
- this->fShow = true;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::SetFlash
- // Accept a char ptr, convert its first four characters to an OSType.
- void
- TFeedback::SetFlash(Ptr theFlash)
- {
- CharToType flashChar;
- flashChar.type = ' ';
- for(short i=0; i<4; i++)
- if(theFlash[i]!=0)
- flashChar.ch[i] = theFlash[i];
- this->fCurrent = flashChar.type;
- this->fShow = true;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::SetFlash
- // Accept a pascal string, convert its first four characters to an OSType.
- void
- TFeedback::SetFlash(Str255 theFlash)
- {
- short len = (theFlash[0]>4)?4:theFlash[0];
- CharToType flashChar;
- flashChar.type = ' ';
- for(short i=0; i<len; i++)
- flashChar.ch[i] = theFlash[i+1];
- this->fCurrent = flashChar.type;
- this->fShow = true;
- }
-
- // ------------------------------------------------------------------------
- // TFeedback::Show
- // Show anything new.
- // When interval is up, erase.
- //
- void
- TFeedback::Show()
- {
- short drawThisCycle=true;
- if(this->fShow)
- {
- if(this->fPrevious)
- {
- // Something is up there, erase it.
- this->Draw(this->fPrevious, kErase);
- // Is this a repeat of the same item?
- if(this->fPrevious==this->fCurrent)
- {
- // Same item, don't draw this cycle.
- // Delay one cycle to make it "flash".
- // Unless the sysbeep is on, that will
- // give enough delay to make it flash.
- drawThisCycle = this->fBeep;
- }
- // Clear our previous item, it was erased.
- this->fPrevious = 0;
- }
- // Auditory feedback and delay between erase and draw.
- if(this->fBeep)
- {
- SysBeep(1);
- }
- // Show.
- if(drawThisCycle)
- {
- this->fShow = false;
- this->fShowTime = TickCount();
- this->Draw(this->fCurrent, kPaint);
- this->fPrevious = this->fCurrent;
- }
- }
- else
- {
- // Nothing new to show.
- // Only erase previous if we have a positive interval.
- if(this->fPrevious && this->fInterval)
- {
- if(TickCount()>this->fShowTime+this->fInterval)
- {
- // Counter timed out and no new stuff.
- // Erase old stuff.
- // Something is up there, erase it.
- this->Draw(this->fPrevious, kErase);
- this->fPrevious = 0;
- }
- }
- }
- }
-
-